Conversation
- `feature/collection/build.gradle.kts`: collection 피처 모듈 빌드 스크립트 정의 및 네임스페이스 설정 - `feature/collection/src/main/AndroidManifest.xml`: 모듈용 매니페스트 파일 추가 - `settings.gradle.kts`: 프로젝트 모듈 목록에 `:feature:collection` 추가
- `libs.versions.toml`: Navigation Compose 라이브러리 버전(2.9.8) 및 카탈로그 정의 추가 - `feature/collection/build.gradle.kts`: `navigation-compose` 라이브러리 의존성 추가 적용
- `CollectionScreen.kt`: `CollectionScreen` 컴포저블 구현 및 프리뷰 추가
- `CollectionActivity.kt`: Hilt 의존성 주입을 위해 `CollectionActivity` 클래스에 `@AndroidEntryPoint` 어노테이션 추가
- `AndroidManifest.xml`: 컬렉션 화면 진입을 위한 `CollectionActivity` 추가 및 세로 방향(portrait) 고정 설정
- `fragment_my_page.xml`: 컬렉션 진입점을 위한 `ComposeView`(`cv_my_page_collection_entry`) 및 하단 구분선(`view_my_page_collection_divider`) 추가 - `fragment_my_page.xml`: 기존 장르 취향 섹션 및 취향 분석 섹션의 상단 제약 조건을 신규 구분선 기준으로 변경하여 레이아웃 구조 조정
- `MyPageFragment.kt`: `cvMyPageCollectionEntry`에 `CollectionEntry` 컴포저블을 적용하는 `setupCollectionEntry` 함수 추가 - `MyPageFragment.kt`: 컬렉션 화면으로 이동하는 `navigateToCollection` 함수 구현 및 연결 - `MyPageFragment.kt`: Compose View의 효율적인 생명주기 관리를 위한 `ViewCompositionStrategy` 설정 추가
|
Warning Review limit reached
Next review available in: 28 minutes Limit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits within each organization. For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. Walkthrough컬렉션 feature 모듈과 Compose 기반 화면을 추가했습니다. Changes컬렉션 기능
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to The PR adds the collection entry flow and navigation structure without any supplied actionable merge-blocking risk; it is merge-ready after normal checks and review. Sequence Diagram(s)sequenceDiagram
participant MyPageFragment
participant CollectionActivity
participant CollectionNavHost
participant CollectionScreen
MyPageFragment->>CollectionActivity: 컬렉션 클릭 후 Intent로 시작
CollectionActivity->>CollectionNavHost: CollectionNavHost 표시
CollectionNavHost->>CollectionScreen: collection 경로로 이동
CollectionScreen-->>CollectionActivity: 컬렉션 화면 표시
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
| import dagger.hilt.android.AndroidEntryPoint | ||
|
|
||
| @AndroidEntryPoint | ||
| class CollectionActivity : ComponentActivity() { |
There was a problem hiding this comment.
activity로 두는게 아닌 SAA 형태로 조금씩 바꾸는게 좋을 것 같습니다. 굳이 레거시 구조를 유지할 이유가 없는 것 같아요
There was a problem hiding this comment.
SAA를 지향하는 방향에는 공감합니다!
다만 현재 앱에는 앱 레벨의 Compose NavHost가 없고, MainActivity가 FragmentContainerView와 FragmentManager를 통해 홈/피드/서재/마이페이지 Fragment를 직접 전환하고 있습니다.
MyPageFragment 역시 이번 작업에서 추가한 것이 아니라 기존 화면입니다.
컬렉션 진입 구조를 설계하면서 아래와 같은 방법들을 고려해보았습니다.
CollectionFragment를 추가하면 기존 Fragment 구조를 다시 확장하게 됩니다.- 컬렉션을
MainActivity의 Compose destination으로 연결하려면 하단 탭, 기존 Fragment 호스팅, 뒤로 가기 처리를 포함한 앱 단위 내비게이션 변경이 필요합니다. - 별도
CollectionActivity를 사용하면 기존 마이페이지와 메인 내비게이션에는 영향을 주지 않으면서, 새로 개발하는 컬렉션 내부 흐름은 Compose Navigation으로 구성할 수 있습니다.
이번 PR은 컬렉션 기능을 단계적으로 추가하는 첫 PR이기 때문에 기존 화면의 마이그레이션까지 범위를 넓히기보다, 수정 범위를 컬렉션에 집중하는 편이 안전하다고 판단해 CollectionActivity를 진입 경계로 선택했습니다. Activity가 추가되어 향후 SAA 전환 시 마이그레이션 대상이 늘어난다는 단점은 있지만, 현재 구조와 PR 범위에서는 가장 적절한 선택이라고 보았습니다.
SAA 로의 전환은 MainActivity 내비게이션 마이그레이션 작업으로 별도 분리하는 것이 적절하다고 생각합니다.
혹시 기존 메인 구조를 크게 변경하지 않으면서 이번 PR에서 점진적으로 적용할 수 있다고 생각하신 구체적인 구조가 있다면 의견 부탁드립니다!
+공식 Android 문서에서도 기존 View/Fragment 앱은 Compose와 공존시키며 화면 단위로 점진적으로 이전하도록 권장하고 있습니다. Fragment가 남아 있는 동안 ComposeView를 사용하는 것도 전환 방식으로 안내하고 있으며, 모든 navigation destination을 Composable로 전환할 수 있을 때 Navigation Compose로 마이그레이션하도록 설명하고 있습니다.
Compose 마이그레이션 전략, ComposeView와 Fragment 연동
There was a problem hiding this comment.
fragment도 현재 compose 환경에서는 잘 사용되지 않아 레거시인것 같습니다.
There was a problem hiding this comment.
Compose-first 구조의 최종 방향에서 Fragment를 제거하는 것이 좋다는 점에는 공감합니다!
다만 MyPageFragment는 이번 작업에서 새로 추가한 것이 아니라 기존 MainActivity의 마이페이지 탭을 구성하던 화면입니다. 이번 PR에서는 기존 마이페이지 전체를 변경하지 않고 컬렉션 진입부만 Compose로 구현하기 위해 ComposeView를 추가했습니다.
MyPageFragment를 제거하려면 기존 마이페이지 XML과 ViewModel 연결, 스크롤 및 툴바 동작 등 컬렉션과 관계없는 영역까지 함께 마이그레이션해야 합니다. 해당 작업은 이번 컬렉션 PR의 범위를 크게 벗어나기 때문에, 따라서 이번에는 기존 Fragment를 유지하고 ComposeView로 점진적 적용하게끔 선택했습니다. 마이페이지 전체의 Compose 전환은 별도 작업으로 분리하는 것이 안전하다고 판단했습니다.
There was a problem hiding this comment.
마이페이지 전체를 compose로 분리하는 것이 아닌 MyPageFragment, HomeFragment, FeedFragment는 지금 그대로 MainActivity의 탭으로 두고, 컬렉션만 앱 레벨 Compose NavHost의 destination으로 붙이면 마이페이지에 대한 이전은 나중에 하고 collection만 간단하게 변경할 수 있을거라 생각됩니다!
여기 ai가 알려준 상세 코드 첨부합니다.
구체적인 방법: MainActivity에 얇은 NavHost 레이어 추가
activity_main.xml에 fcv_main 위를 덮는 ComposeView 하나만 추가합니다.
<androidx.compose.ui.platform.ComposeView
android:id="@+id/cv_main_overlay"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
MainActivity에 앱 레벨 NavHost를 두되, startDestination은 아무것도 그리지 않는 main 으로 둡니다. 즉 기본 상태에서는 기존 Fragment 화면이 그대로 보이고, Compose destination으로
이동한 순간에만 오버레이가 올라옵니다.
// app/src/main/java/com/into/websoso/ui/main/AppNavHost.kt
@composable
fun AppNavHost(
navController: NavHostController,
modifier: Modifier = Modifier,
) {
NavHost(navController, startDestination = MainRoute, modifier = modifier) {
composable { } // Fragment 탭 영역 — 아무것도 그리지 않음
collectionNavGraph(navController) // feature:collection이 제공하는 그래프
}
}
// MainActivity
private lateinit var navController: NavHostController
private fun setupComposeNavHost() {
binding.cvMainOverlay.apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
navController = rememberNavController()
WebsosoTheme { AppNavHost(navController) }
val entry by navController.currentBackStackEntryAsState()
val isRoot = entry?.destination?.hasRoute<MainRoute>() ?: true
LaunchedEffect(isRoot) {
binding.cvMainOverlay.isVisible = !isRoot
binding.fcvMain.isVisible = isRoot
binding.bnvMain.isVisible = isRoot
binding.viewMainDivider.isVisible = isRoot
backPressedCallback.isEnabled = isRoot // ★ 중요
}
}
}
}
|
|
||
| implementation(projects.data.account) | ||
| implementation(projects.data.library) | ||
| implementation(projects.data.feed) |
There was a problem hiding this comment.
지금 아키텍쳐가 feature based layered architecture 구조인데 feature에 대한 데이터 모듈과 feed가 같은 레벨에 있는게 조금 이상한 것 같습니다
There was a problem hiding this comment.
확인해 보니 코멘트가 달린 implementation(projects.data.feed) 의존성은 기존에 존재하던 코드이고, 이번 PR에서 app/build.gradle.kts에 추가한 의존성은 implementation(projects.feature.collection) 한 줄입니다.
feature.collection은 기존 feature.signin, feature.library, feature.feed와 동일한 feature 레벨에 추가했습니다. 또한 이번 PR에는 컬렉션 API나 데이터·도메인 로직이 포함되지 않아 collection용 data/domain 모듈은 아직 추가하지 않았습니다.
혹시 기존 app → data.feed/domain.feed 직접 의존 구조를 말씀하신 것인지, 아니면 이번에 추가한 feature.collection의 모듈 위치가 적절하지 않다는 의견인지 확인 부탁드립니다.
후자라면 생각하신 구체적인 모듈 배치나 의존 방향을 알려주시면 다시 고려해보겠습니다!
There was a problem hiding this comment.
말씀하신 부분을 app이 data.feed, domain.feed, feature.feed를 모두 직접 의존하고 있어 feature 기반 의존 방향과 맞지 않는다는 의미로 이해했습니다.
확인해 보니 현재 app의 기존 피드 상세 및 작성 화면에서 data.feed의 Repository와 Entity를 직접 사용하고 있어 해당 의존성이 남아 있습니다. 이 부분은 이번 PR에서 추가된 의존성이 아니라 기존 피드 모듈화 과정에서 남아 있는 구조이며, 제거하려면 관련 피드 화면과 데이터 참조를 함께 feature.feed 쪽으로 이전해야 할 것 같습니다.
이번 PR에서 app/build.gradle.kts에 추가한 것은 projects.feature.collection 한 줄이며, 컬렉션에는 아직 데이터 계층이 포함되지 않습니다. 기존 app → data.feed/domain.feed 의존 정리는 피드 모듈화 작업으로 별도 분리하는 것이 적절하다고 생각하는데, 제가 리뷰 의도를 맞게 이해했을까요?
There was a problem hiding this comment.
네 맞습니다 지금 collection의 모듈에는 data, domain, presentation 이렇게 있어야 될거같은데, data와 domain 이 collectio모듈과 같은 레벨에 있어 개념상 맞지 않는다고 판단했습니다. 그래서 collection/data, domain, presentation 이렇게 하위 모듈로 가져가고 각 feature끼리는 domain 만 서로 의존하는 것이 더 좋은 설계인 것 같습니다! 다만 변경 범위가 커서 collection 만 우선적으로 옮겨가는 것이 좋아보입니다.
- `CollectionEntry.kt`: 클릭 시 중복 호출을 방지하기 위해 `clickable`을 `debouncedClickable`로 변경 - `MyPageFragment.kt`: UI 컴포넌트 수준에서 중복 클릭이 제어됨에 따라 `navigateToCollection` 내의 `singleEventHandler.throttleFirst` 로직 제거
- `CollectionEntry.kt`: `buildAnnotatedString`을 사용하여 여러 개의 `Text` 컴포저블로 나뉘어 있던 컬렉션 개수 표시 로직을 단일 컴포저블로 통합 및 스타일링 코드 최적화
📌𝘐𝘴𝘴𝘶𝘦𝘴
📎𝘞𝘰𝘳𝘬 𝘋𝘦𝘴𝘤𝘳𝘪𝘱𝘵𝘪𝘰𝘯
Overview
컬렉션 기능을 기존 앱과 분리해 확장할 수 있도록
feature:collection모듈과 전용 진입 구조를 추가합니다.마이페이지의 컬렉션 항목에서 별도
CollectionActivity로 이동하고, Activity 내부에서는 Navigation Compose 기반의CollectionNavHost가 컬렉션 화면 흐름을 담당합니다.작업 배경
기존
app모듈의 마이페이지는 XML 기반 화면이므로, 컬렉션 진입 UI만ComposeView로 삽입해 기존 화면 구조를 유지했습니다.컬렉션 내부 화면은 이후 목록·생성·검색 화면이 추가될 것을 고려해 별도 feature 모듈과 Activity, NavHost를 진입 경계로 사용합니다.
이 PR은 컬렉션 전체 작업을 나눈 Stacked PR의 첫 번째 단계이며, 실제 컬렉션 목록과 생성·검색 기능은 후속 PR에서 다룹니다.
주요 변경 사항
1. 컬렉션 feature 모듈 구성
feature:collection모듈 및 AndroidManifest 추가app모듈에 컬렉션 모듈 연결2.9.8등록2. 컬렉션 전용 Activity 및 내부 Navigation 구성
CollectionActivity추가@AndroidEntryPoint적용exported=false로 등록WebsosoTheme안에서CollectionNavHost실행CollectionScreen연결3. 마이페이지 컬렉션 진입부 연결
ComposeView추가DisposeOnViewTreeLifecycleDestroyed적용CollectionEntry구현SingleEventHandler.throttleFirst패턴 재사용CollectionActivity실행이번 PR에서 제외한 범위
위 기능은 후속 Stacked PR에서 단계별로 추가합니다.
검증
./gradlew testDebugUnitTest :app:assembleDebug ktlintCheck --console=plain📷𝘚𝘤𝘳𝘦𝘦𝘯𝘴𝘩𝘰𝘵
💬𝘛𝘰 𝘙𝘦𝘷𝘪𝘦𝘸𝘦𝘳𝘴
리뷰 포인트
app → feature:collection의존 방향이 기존 멀티 모듈 구조에 적합한지ComposeView생명주기 설정이 적절한지0으로 표시되는 점Stacked PR 안내
developfeat/933feat/933을 base로 하여 컬렉션 목록 UI 변경만 분리할 예정입니다.Summary by CodeRabbit
새로운 기능